﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Linq.Expressions;
using System.Collections;
using System.Runtime.Serialization;

namespace Lib.Query
{
    [Serializable()]
    [DataContract]    
    public class LiteQuery<T> : Lib.Query.IUntypedLiteQuery
    {        
        public virtual Type EntityType { get { return typeof(T);  } }

        public LiteQuery<T> Add(Expression<Func<T, object>> expression, CriteriaOperator criteriaOperator, object value)
        {
            string propertyName = LambdaExpressionHelper.ResolvePropertyName<T>(expression);
            Add(propertyName, criteriaOperator, value);
            return this;
        }

        public LiteQuery<T> OrderBy(Expression<Func<T, object>> expression, bool ascending)
        {
            string propertyName = LambdaExpressionHelper.ResolvePropertyName<T>(expression);
            OrderBy(propertyName, ascending);
            return this;
        }

        public LiteQuery<T> Add<TChild>(Expression<Func<TChild, object>> expression, CriteriaOperator criteriaOperator, object value) where TChild : T
        {            
            string propertyName = LambdaExpressionHelper.ResolvePropertyName<TChild>(expression);
            Add(propertyName, criteriaOperator, value);
            return this;
        }

        public LiteQuery<T> OrderBy<TChild>(Expression<Func<TChild, object>> expression, bool ascending) where TChild : T
        {         
            string propertyName = LambdaExpressionHelper.ResolvePropertyName<TChild>(expression);
            OrderBy(propertyName, ascending);
            return this;
        }
          
        public void OrderBy(string propertyName, bool ascending)
        {
            if (_orderByClause == null)
                _orderByClause = new Query.OrderByClause();

            _orderByClause.PropertyName = propertyName;
            _orderByClause.Ascending = ascending;        
        }

        public void Top(int n)
        {
            _topN = n;        
        }

        public void Operator(QueryOperator queryOperator)
        {
            _queryOperator = queryOperator;        
        }
        
        public int _pageNumber;

        [DataMember]
        public int PageNumber
        {
            get { return _pageNumber; }
            set { _pageNumber = value; }
        }

        public int PageIndex
        {
            get { return PageNumber - 1; }
        }
        
        public int _pageSize;

        [DataMember]
        public int PageSize
        {
            get { return _pageSize; }
            set { _pageSize = value; }
        }
        
        protected int _topN;

        [DataMember]
        public int TopN 
        { 
            get { return _topN; }
            set { _topN = value; }
        }

        protected OrderByClause _orderByClause;

        [DataMember]
        public OrderByClause OrderByClause 
        { 
            get { return _orderByClause; }
            set { _orderByClause = value; }
        }        

        protected QueryOperator _queryOperator;
        [DataMember]
        public QueryOperator QueryOperator 
        { 
            get { return _queryOperator; }
            set { _queryOperator = value; }
        }

        public LiteQuery()
        {
            _criteria = new List<Criteria>();
            _topN = 0;            
            _queryOperator = QueryOperator.And;
            _orderByClause = null;            
        }

        protected List<Criteria> _criteria;
        [DataMember]
        public List<Criteria> Criteria
        {
            get { return _criteria; }
            set { _criteria = value; }
        }

        public void Add(string propertyName, CriteriaOperator criteriaOperator, object value)
        {
            Criteria andCriteria = new Criteria(propertyName, value, criteriaOperator);
            _criteria.Add(andCriteria);            
        }
        
        /*        
        public LiteQuery<TEntity> From(string viewName)
        {
            return this;
        }

        public LiteQuery<TEntity> Fields(string field)
        {
            return this;
        }*/
    }
}